// 将axios单独封装到一个js模块中
import axios from 'axios'
// 导入 store
import store from '@/store'
// 导入json-bigint包
import JSONbig from 'json-bigint'
// 导入路由
import router from '@/router'
// 导入刷新用户的token的api
import { reqGetNewToken } from '@/api/user'
// 原地址: http://ttapi.research.itcast.cn/app/
// 现地址: http://toutiao-app.itheima.net/，需要去掉/app路径
// 原接口：url: '/app/v1_1/articles'，现在需要删除'app'：url: '/v1_1/articles'
const http = axios.create({
  // baseURL: 'http://ttapi.research.itcast.cn/app/',  原地址
  baseURL: 'http://toutiao-app.itheima.net/',
  timeout: 5000,
  // axios默认会对响应的数据做JSON.parse处理,不用axios 默认帮我们处理了自己来定制(修改)响应数据
  // 添加这个配置项之后，axios默认的返回失效,以transformResponse配置的为准
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    try {
      return JSONbig.parse(data) // 数据在交互的时候都是json字符串
    } catch (error) {
      return data // 优化,以后遇到响应的数据问题让后台处理
    }
  }]
})

// 请求/响应拦截
// 添加请求拦截器
http.interceptors.request.use(function (config) {
  // console.log('进入请求拦截器')
  // 在发送请求之前做些什么
  // console.log(config) // 请求的信息对象
  const token = store.state.user.tokenInfo.token
  // 如果Authorization被挂载过 不需要进行二次挂载  二次挂载会进行覆盖
  if (token && !config.headers.Authorization) { // 如果获取到了token 再向请求头中加token
    config.headers.Authorization = 'Bearer ' + token
  }
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
http.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  // console.log(response)
  return response.data
}, async function (error) {
  // 对响应错误做点什么
  // console.dir(error)  error响应结果, 存储的是响应失败的信息
  // error中有一个response对象.这个对象中status 如果这个值是401 ,表示token有问题
  // console.dir(error)
  // 如果error.response.status === 401 说明token异常
  if (error.response.status === 401) {
    // 如果有refresh_token 刷新token  否则就去登录
    const refresh_token = store.state.user.tokenInfo.refresh_token
    if (refresh_token) {
      try {
        console.log('执行刷新token') // 下次写获取新token
        // 1.准备接口 2.调接口刷新新的token
        const data = await reqGetNewToken(refresh_token)
        // console.log(data.data.token) // 服务器返回最新的token
        const newToken = data.data.token
        // 3. 将token存储在vuex
        store.commit('user/setTokenInfo', {
          token: newToken,
          refresh_token
        })
        // 4. 重新发送请求
        // error.config 就是上一次请求失败的ajax请求 只需要重新发送这个请求就可以了
        // 更新headers旧的token
        error.config.headers.Authorization = 'Bearer ' + newToken // 这个必须写要不认会死循环
        return http(error.config)
      } catch (error) {
        // 如果手动将refresh_token也失效了,新的token是获取不到
        // 1. 将vuex和本地存储的tokenInfo清除
        store.commit('user/removeTokenInfo')
        // 2. 让用户重新登录
        router.push({
          path: '/login',
          query: { // 携带参数让用户成功登录之后原路返回
            backTo: router.currentRoute.fullPath
          }
        })
      }
    } else {
      // console.log('去登录页面')
      // 如果进入这个分支, 没有refresh_token 也将本地存储的破坏了的tokenInfo移除
      // 提交一个mutation 将vuex中tokenInfo移除
      store.commit('user/removeTokenInfo')
      // router.push('/login') // 还需要原路返回的
      console.log(router.currentRoute.path) // 当前激活的路由信息对象  // router.currentRoute === this.$route
      router.push({
        path: '/login',
        query: { // 携带参数让用户成功登录之后原路返回
          backTo: router.currentRoute.fullPath
        }
      })
    }
  }
  return Promise.reject(error)
})

// 导出 在main.js中导入 并挂载给vue原型
export default http
// Promise.then(function(){},function(){)

// 双token认证  token 和refresh_token  ,真正发送请求携带的一直是token,但是token会过期,过期之后需要使用refresh_token
// 获取先的token 想做用户只登录一次就再也不需要登录的操作
